package com.gridmobi.xrtb.common;

import com.google.common.util.concurrent.RateLimiter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BudgetBasedRateLimiter {
    private volatile RateLimiter rateLimiter;
    private volatile Float totalDailyBudget; // 每日总预算
    private volatile Float spentBudget; // 已消耗的预算
    private volatile Float perPrice; // 每次操作的预算值

//    public BudgetBasedRateLimiter(long totalDailyBudget, long perPrice) {
//        this.totalDailyBudget = totalDailyBudget;
//        this.perPrice = perPrice;
//        this.spentBudget = 0;
//        // 初始速率设定为每日总预算除以一天的秒数，作为起点
//        this.rateLimiter = RateLimiter.create((double) totalDailyBudget / 86400);
//    }

    public static long getChnSeconds() {
        // 获取当前UTC时间
        LocalDateTime now = LocalDateTime.now();

        // 转换为北京时间
        ZonedDateTime beijingTime = now.atZone(ZoneId.of("Asia/Shanghai"));

        // 获取当日北京时间的次日零点
        ZonedDateTime nextDayMidnight = beijingTime.toLocalDate().atStartOfDay(ZoneId.of("Asia/Shanghai"));

        // 计算剩余秒数
        long remainingSeconds = ChronoUnit.SECONDS.between(beijingTime, nextDayMidnight);

        return remainingSeconds;
    }

    public static long getLeftSeconds() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 获取当前日期的次日开始时间
        LocalDateTime nextDayStart = now.toLocalDate().plusDays(1).atStartOfDay();
        // 计算时间差
        Duration durationUntilEndOfDay = Duration.between(now, nextDayStart);
        // 获取剩余秒数
        long secondsLeft = durationUntilEndOfDay.getSeconds();

     return secondsLeft;
    }

    public BudgetBasedRateLimiter(Float totalDailyBudget, Float spentBudget, Float perPrice) {
        this.totalDailyBudget = totalDailyBudget;
        this.spentBudget = spentBudget;
        this.perPrice = perPrice;
        float leftCounts = (totalDailyBudget - spentBudget) / perPrice;
        long remainingSeconds = getLeftSeconds();
        this.rateLimiter = RateLimiter.create((double) (leftCounts * 1000 * 20)/ remainingSeconds);
    }

    public synchronized boolean tryAcquire(Float spent) {
        Float remainingBudget = totalDailyBudget - spentBudget;
        if (remainingBudget <= 0) {
            return false;
        }
        if (remainingBudget < spent) {
            // 如果剩余预算不足以支持一次操作，则不允许操作
            return false;
        }

        boolean acquired = rateLimiter.tryAcquire();
//        if (acquired) {
//            // 成功获取许可，更新已消耗预算
//            updateSpentBudget(spent);
//        }
        return acquired;
    }

    private void updateSpentBudget(Float spent) {
        this.spentBudget += spent;
        adjustRateLimiter();
    }

    private void adjustRateLimiter() {
        Float remainingBudget = totalDailyBudget - spentBudget;
        long remainingSeconds = TimeUnit.MILLISECONDS.toSeconds(TimeUnit.DAYS.toMillis(1) - System.currentTimeMillis() % TimeUnit.DAYS.toMillis(1));
        double newRate = (double) remainingBudget / (remainingSeconds * perPrice);
        rateLimiter.setRate(newRate);
    }

    // 剩下的方法可以根据需要实现
}
